home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Alles Voor Internet / Tout Pour Internet
/
alles voor internet.iso
/
MacInternet™
/
Telnet
/
NCSA
/
tn3270 2.4d7 source
/
tn3270
/
scrap.c
< prev
next >
Wrap
Text File
|
1992-04-17
|
20KB
|
878 lines
/*
* tn3270 for the Macintosh Source Code
* Brown University Computing and Information Services
* Version 2.4d7 April, 1992
* Copyright (c) 1988, 1989, 1990, 1991, 1992 by Brown University and by
* Peter John DiCamillo.
*
* Permission is granted to any individual or institution to use, copy,
* or redistribute the binary version of this software and its
* documentation provided this notice and the copyright notices are
* retained. Permission is granted to any individual or non-profit
* institution to use, copy, modify, or redistribute the source files
* of this software provided this notice and the copyright notices are
* retained. This software may not be distributed for profit, either
* in original form or in derivative works, nor can the source be
* distributed to other than an individual or a non-profit institution.
* Any individual or group interested in seeing and/or using these
* source files but who are prevented from doing so by the above
* constraints should contact Don Wolfe, Assistant Vice-President for
* Computer Systems at Brown University, (401) 863-7250, for possible
* software licensing of the source developed at Brown.
*
* Brown University and Peter John DiCamillo make no representations
* about the suitability of this software for any purpose.
*
* BROWN UNIVERSITY AND PETER JOHN DICAMILLO GIVE NO WARRANTY, EITHER
* EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED,
* INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY AND
* WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#if !defined(USEDUMP)
#include "maclib.h"
#include "termdef.h"
#include "tn3270funcs.h"
#include "globals.h"
#else
#pragma load "tn3270DumpFile"
#endif
#include "telnet.h"
#pragma segment 3270seg2
static char tableflag = 0;
static char textflag = 0;
static char calcflag;
static long calcsize;
static unsigned char * scrapptr;
static unsigned char * expresult;
static unsigned short * expresattr;
OSErr newscrap(cnr *cp)
{
long allocsize;
scrapline * sp;
unsigned char * chrptr;
short i;
/* Return if there is already a scrap which is large enough */
if ((scrapstart != 0) && (scrapwidth >= cp->cs.altcols)
&& (scrapalloc >= cp->cs.altrows)) {
return(noErr);
}
/* Allocate new scrap */
if (scrapstart != 0) {
removescrap(); /* remove scrap which is too small */
/* uses value of scrapalloc */
if (cp->cs.altrows > scrapalloc) /* permanent allocation is one screen */
scrapalloc = cp->cs.altrows;
if (cp->cs.altcols > scrapwidth)
scrapwidth = cp->cs.altcols;
}
else {
scrapalloc = cp->cs.altrows;
scrapwidth = cp->cs.altcols;
}
allocsize = sizeof(struct scrapline) * scrapalloc;
allocsize += scrapalloc * scrapwidth * 3; /* 1 byte for char, 2 for attrs. */
allocsize += scrapwidth * 3; /* for expresult and expresattr */
scrapstart = (scrapline *)myNewPtr(allocsize, 0);
if (scrapstart == 0) {
return(1);
}
chrptr = (unsigned char *)scrapstart;
chrptr += sizeof(struct scrapline) * scrapalloc;
sp = scrapstart;
for (i=0; i < scrapalloc-1; i++) {
sp->nextline = sp + 1;
sp->text = chrptr;
chrptr += scrapwidth;
sp->attr = (unsigned short *)chrptr;
chrptr += scrapwidth * 2;
sp++;
}
sp->nextline = 0;
sp->text = chrptr;
chrptr += scrapwidth;
sp->attr = (unsigned short *)chrptr;
chrptr += scrapwidth * 2;
expresult = chrptr;
chrptr += scrapwidth;
expresattr = (unsigned short *)chrptr;
scrapsize = 0; /* no lines in use */
return(0);
}
void removescrap(void)
{
scrapline *sp, *nextsp;
if (scrapstart == 0) {
return;
}
exportscrap(1); /* copy private scrap to desk scrap */
/* return private scrap storage */
sp = scrapstart;
sp += scrapalloc - 1; /* sp -> last permanent element */
nextsp = sp->nextline; /* nextsp -> first extra element, if any */
while (nextsp != 0) { /* free each extra element */
sp = nextsp;
nextsp = sp->nextline;
DisposPtr((Ptr)sp);
}
DisposPtr((Ptr)scrapstart); /* free permanent elements */
scrapstart = 0;
if (pasteok && usemyscrap) {
pasteok = usemyscrap = 0;
}
}
void importscrap(void)
{
long offset, ssize;
scrapsize = 0; /* discard my scrap */
ssize = GetScrap(0, 'TEXT', &offset);
pasteok = (ssize > 0);
usemyscrap = 0;
}
void exportscrap(char endflag)
{
unsigned char * scrapmem;
OSErr rc;
if (scrapsize == 0) return; /* nothing to do if no scrap */
/* calculate size of exported scrap */
calcsize = 0;
calcflag = 1;
doexport();
/* return if size = 0 */
if (calcsize == 0) return;
/* allocate memory to hold scrap */
scrapmem = (unsigned char *)myNewPtr(calcsize, 0);
if (scrapmem == 0) {
beep(0);
return;
}
/* initialize scrap */
rc = ZeroScrap();
if (rc != 0) {
DisposPtr(scrapmem);
beep(0);
return;
}
/* copy data to scrap and return storage */
scrapptr = scrapmem;
calcflag = 0;
doexport();
rc = PutScrap(calcsize, 'TEXT', scrapmem);
DisposPtr(scrapmem);
if (rc != 0) {
beep(0);
return;
}
/* if end call, load scrap into memory */
if (endflag) LoadScrap();
}
void doexport(void)
{
register short col;
short startoff, len, colstart, colend;
short linecount;
char expstate, initsel, sel, anytext;
scrapline * sp;
scrapline currline;
sp = scrapstart;
linecount = 0;
anytext = 0;
while (linecount < scrapsize) {
currline = *sp; /* make local copy of current line */
/* find first selected printable character */
colstart = 0;
initsel = 0;
while (colstart < scrapwidth) {
if ((currline.attr)[colstart] & 0x0020) {
if (((currline.text)[colstart] != 0) &&
((currline.text)[colstart] != 0x40) &&
(((currline.attr)[colstart] & 0x8000) == 0)) {
if ((initsel == 0) && textflag && anytext) expbreak();
anytext = initsel = 1;
break;
}
else {
if ((initsel == 0) && textflag) {
expendline();
anytext = 0;
}
initsel = 1;
}
}
colstart++;
}
/* if no printable characters, output null line */
if (colstart == scrapwidth) {
if (initsel) {
expendline();
anytext = 0;
}
linecount++;
sp = sp->nextline;
continue;
}
/* find last printable character */
colend = scrapwidth - 1;
while (colend >= 0) {
if (((currline.attr)[colend] & 0x0020) &&
((currline.text)[colend] != 0) &&
((currline.text)[colend] != 0x40) &&
(((currline.attr)[colend] & 0x8000) == 0)) break;
else colend--;
}
expstate = 0;
initsel = 0;
for (col = colstart; col <= colend; col++) {
sel = ((currline.attr)[col] & 0x0020) != 0;
if (tableflag || (!initsel)) {
sel = sel && ((currline.text)[col] != 0)
&& ((currline.text)[col] != 0x40)
&& (((currline.attr)[col] & 0x8000) == 0);
initsel = sel;
}
switch(expstate) {
case 0: /* before first field */
if (sel) {
startoff = col;
len = 1;
expstate = 1;
}
break;
case 1: /* within field */
if (sel) {
len++;
}
else {
expfield(&currline, startoff, len);
startoff = col;
len = 1;
expstate = 2;
initsel = 0;
}
break;
case 2: /* between fields */
if (sel) {
expbreak();
startoff = col;
len = 1;
expstate = 1;
}
else {
len++;
}
break;
default:
break;
}
}
switch(expstate) { /* end-of-line processing */
case 0: /* before first field */
break;
case 1: /* within field */
expfield(&currline, startoff, len);
if (!textflag) expendline();
break;
case 2: /* between fields */
if (!textflag) expendline();
break;
default:
break;
}
linecount++;
sp = sp->nextline;
}
}
void expfield(scrapline *sp, short offset, short len)
{
short linelen;
register short i;
char alaflag, dcflag;
scrapline currline;
currline = *sp; /* make copy of current line */
/* adjust offset and length to eliminate leading blanks, nulls, and
attributes (shouldn't happen). */
while (len > 0) {
if (((currline.text)[offset] == 0x00) ||
((currline.text)[offset] == 0x40) ||
((currline.attr)[offset] & 0x8000)) {
offset++;
len--;
}
else break;
}
/* adjust length to eliminate trailing blanks, nulls, and attributes */
while (len > 0) {
if (((currline.text)[offset+len-1] == 0x00) ||
((currline.text)[offset+len-1] == 0x40) ||
((currline.attr)[offset+len-1] & 0x8000)) {
len--;
}
else break;
}
/* skip field if no printable characters (shouldn't happen) */
if (len == 0) return;
/* copy field to buffer, handling nulls, and replacing attribute
bytes by blanks */
linelen = 0;
dcflag = 0;
alaflag = (scrap_stdfont == ALAFONT);
for (i=0; i < len; i++) {
if ((currline.attr)[offset+i] & 0x8000) {
expresult[linelen] = 0x40;
expresattr[linelen++] = (currline.attr)[offset+i];
if (alaflag) {
expresattr[linelen] &= 0xff00;
dcflag = 0;
}
}
else if ((currline.text)[offset+i] == 0x00) {
if (scrap_repnull) {
expresult[linelen] = 0x40;
expresattr[linelen++] - (currline.attr)[offset+i];
if (alaflag) {
expresattr[linelen] &= 0xff00;
dcflag = 0;
}
}
}
else {
if (alaflag) {
if (alatype((currline.text)+offset+i) == 2) { /* is a diacritic */
expresult[linelen] = (currline.text)[offset+i];
expresattr[linelen++] = (currline.attr)[offset+i] & 0xff00;
dcflag = 1;
}
else { /* not a diacritic */
if (dcflag) {
if ((currline.text)[offset+i] != 0x40) {
expresattr[linelen-1] |= (currline.text)[offset+i];
}
dcflag = 0;
}
else {
expresult[linelen] = (currline.text)[offset+i];
expresattr[linelen++] = (currline.attr)[offset+i] & 0xff00;
}
}
}
else {
expresult[linelen] = (currline.text)[offset+i];
expresattr[linelen++] = (currline.attr)[offset+i];
}
}
}
/* translate from EBCDIC to Mac ASCII */
for (i=0; i < linelen; i++)
if (expresattr[i] & 0x4000) { /* APL character */
expresult[i] = (*xtabh)[expresult[i] + 256];
}
else {
if (scrap_nlhandle != 0) {
expresult[i] = (*xtabh)[scrap_nltab[expresult[i]]];
}
else {
if (alaflag) {
expresult[i] = alatrans(expresult[i], expresattr[i] & 0xff);
}
else {
expresult[i] = (*xtabh)[expresult[i]];
}
}
}
/* add to the desk scrap */
myPutScrap(linelen, expresult);
}
unsigned char alatrans(unsigned char dc, unsigned char chr)
{
unsigned char *chrlist, *dclist, *dcdata;
register short i;
short chrindex, dcindex;
unsigned char c;
if (chr == 0) return((*xtabh)[dc+512]); /* no diacritic */
chrlist = (*alaxtabh);
dclist = chrlist+16;
dcdata = chrlist+32;
/* get table index for character */
chrindex = -1;
for (i=0; i < 16; i++) {
if (chrlist[i] == 0) break;
if (chr == chrlist[i]) {
chrindex = i;
break;
}
}
if (chrindex < 0) return((*xtabh)[chr+512]);
/* get table index for diacritic */
dcindex = -1;
for (i=0; i < 16; i++) {
if (dclist[i] == 0) break;
if (dc == dclist[i]) {
dcindex = i;
break;
}
}
if (dcindex < 0) return((*xtabh)[chr+512]);
c = dcdata[(dcindex << 4) + chrindex];
if (c == 0) return((*xtabh)[chr+512]);
else return(c);
}
void expbreak(void)
{
unsigned char breakchar[1];
if (tableflag) breakchar[0] = 0x09;
else breakchar[0] = 0x20;
myPutScrap(1, breakchar);
}
void expendline(void)
{
static unsigned char endchar[1] = 0x0d;
myPutScrap(1, endchar);
}
void myPutScrap(short len, unsigned char *data)
{
if (calcflag) {
calcsize += len;
return;
}
memcpy(scrapptr, data, len);
scrapptr += len;
}
void scrapcut(char append, cnr *cp)
{
register unsigned short i, offset, a, attroff;
char protfield, protflag;
tableflag = textflag = 0;
scopy(append, cp);
if (!(cp->fmtscrn)) {
cp->cutflag = 1;
for (i=0; i < cp->maxcnt; i++) {
if ((cp->atrbuff)[i] & 0x0020) dselchar(i, 0, cp);
}
cp->cutflag = 0;
invldscr(cp);
return;
}
offset=firstattr(cp);
cp->cutflag = 1;
protflag = 0;
for (i=0; i < cp->maxcnt; i++) {
a = (cp->atrbuff)[offset];
if (a & 0x8000) { /* handle attribute byte */
protfield = (a & 0x2000) != 0;
attroff = offset;
}
if (((a & 0x8020) == 0x0020) && (!protfield)) {
dselchar(offset, attroff, cp);
}
else {
if (a & 0x0020) protflag = 1;
}
offset++;
if (offset > cp->maxoff) offset = 0;
}
invldscr(cp);
if (protflag) beep(cp);
cp->cutflag = 0;
}
void scrapcopy(char append, cnr *cp)
{
tableflag = textflag = 0;
scopy(append, cp);
}
void scrappaste(cnr *cp)
{
unsigned char *scrapmem;
long slength, soffset;
Handle shandle;
short i, k, ssize;
unsigned char schar;
/* get the stream of characters to paste */
if (usemyscrap) {
if (scrapsize == 0) return; /* nothing to do if no scrap */
/* calculate size of exported scrap */
calcsize = 0;
calcflag = 1;
doexport();
/* return if size = 0 */
if (calcsize == 0) return;
ssize = calcsize;
/* allocate memory to hold scrap */
scrapmem = (unsigned char *)myNewPtr(calcsize, cp);
if (scrapmem == 0) {
beep(cp);
return;
}
/* initialize scrap */
/* copy data to scrap and return storage */
scrapptr = scrapmem;
calcflag = 0;
doexport();
}
else {
shandle = NewHandle(0);
slength = GetScrap(shandle, 'TEXT', &soffset);
if (slength <= 0) {
beep(cp);
return;
}
scrapmem = (unsigned char *)myNewPtr(slength, cp);
if (scrapmem == 0) {
beep(cp);
return;
}
memcpy(scrapmem, *shandle, slength);
DisposeHandle(shandle);
ssize = slength;
}
if (ssize <= 0) {
DisposPtr(scrapmem);
return;
}
switch(cp->connstate) {
case 4:
break;
case 5:
break;
case 1:
if (cp->serflg) break;
default:
DisposPtr(scrapmem);
beep(cp); /* error if wrong state for input */
return;
}
if (cp->vmxbgn && (!(cp->vmxsub))) {
DisposPtr(scrapmem);
beep(cp); /* error if xfer mode */
return;
}
/* process serial line mode paste */
if (cp->serflg && (cp->connstate != 5)) {
for (i = 0; i < ssize; i++) {
schar = scrapmem[i];
if (cp->servermode) {
putsrv(&schar, 1, 1, cp);
}
else {
serout(schar);
}
}
DisposPtr(scrapmem);
return;
}
/* process tcp server line mode paste */
if ((cp->connstate != 5) && cp->servermode) {
for (i = 0; i < ssize; i++) {
schar = scrapmem[i];
putsrv(&schar, 1, 1, cp);
}
DisposPtr(scrapmem);
return;
}
/* tcp line mode paste */
if (cp->connstate != 5) {
cp->pastebuff = myNewPtr(ssize, cp); /* allocate buffer */
if (cp->pastebuff == 0) {
DisposPtr(scrapmem);
beep(cp);
return;
}
cp->pastebuffsize = 0;
for (i = 0; i < ssize; i++) {
schar = scrapmem[i];
/* echo unless telnet host is doing it */
if (!(cp->hisopts)[TELOPT_ECHO]) {
putscr(&schar, 1, 0, cp);
}
if (schar > 127) continue;
(cp->pastebuff)[cp->pastebuffsize++] = schar;
}
tcpwrite(cp->pastebuff, cp->pastebuffsize, cp);
DisposPtr(cp->pastebuff);
cp->pastebuffsize = 0;
DisposPtr(scrapmem);
return;
}
/* 3270 mode paste */
if (cp->pastebuffsize != 0) { /* error if already doing paste */
DisposPtr(scrapmem);
beep(cp);
return;
}
if (cp->kbqsize > (KBQMAX-1)) { /* one keyboard queue entry needed */
DisposPtr(scrapmem);
beep(cp);
return;
}
cp->pastebuff = myNewPtr(ssize, cp); /* allocate paste queue */
if (cp->pastebuff == 0) {
DisposPtr(scrapmem);
beep(cp);
return;
}
/* store character codes in queue */
cp->pastebeep = 0;
cp->pastebuffsize = 0;
for (i = 0; i < ssize; i++) {
schar = scrapmem[i];
if (schar == 0x0d) k = 0xb4; /* newline */
else if (schar == 0x09) k = 1; /* tab -> space */
else k = (*(cp->kb_handle))[schar+640];
if (k == 0) continue;
k -= 1;
if ((kbtyp[k] & 0x0f) == 2) continue; /* auto-key */
if (k==254) continue; /* overriding hex mapping */
/* add to queue */
(cp->pastebuff)[cp->pastebuffsize++] = k;
}
/* put special paste entry into keyboard queue */
(cp->kbqueue)[cp->kbqsize].code = 0;
(cp->kbqueue)[cp->kbqsize++].shift = 100;
DisposPtr(scrapmem);
}
void scrapclear(cnr *cp)
{
selclear(0x00, cp);
}
void scrapcopytable(char append, cnr *cp)
{
tableflag = 1;
textflag = 0;
scopy(append, cp);
}
void scrapcopytext(char append, cnr *cp)
{
tableflag = 0;
textflag = 1;
scopy(append, cp);
}
void scopy(char append, cnr *cp)
{
register short rowoff, coloff;
short i;
char found, scrapinit, scrapappend;
scrapline * sp, *nextsp;
unsigned char *chrptr;
long allocsize;
scrapinit = scrapappend = 0;
scrap_stdfont = cp->stdfont;
scrap_nlhandle = cp->nl_handle;
scrap_repnull = cp->cs.repnull;
memcpy(scrap_nltab, cp->nltab, 256);
for (rowoff = 0; rowoff < cp->maxcnt; rowoff += cp->scrhsize) {
found = 0;
for (coloff = 0; coloff < cp->scrhsize; coloff++)
if ((cp->atrbuff)[rowoff+coloff] & 0x0020) {
found = 1;
break;
}
if (!found) continue;
if (!scrapinit) { /* set sp before adding first line */
scrapinit = 1;
if (!append) scrapsize = 0;
sp = scrapstart;
if (scrapsize > 1)
for (i=0; i < scrapsize-1; i++) sp = sp->nextline;
}
/* add new line after last line */
if (scrapsize > 0) {
if (sp->nextline == 0) {
allocsize = sizeof(struct scrapline);
allocsize += scrapwidth * 3;
sp->nextline = (struct scrapline *)myNewPtr(allocsize, cp);
if (sp->nextline == 0) {
beep(cp);
return;
}
scrapappend = 1;
(sp->nextline)->nextline = 0;
chrptr = (unsigned char *)sp->nextline;
chrptr += sizeof(struct scrapline);
(sp->nextline)->text = chrptr;
chrptr += scrapwidth;
(sp->nextline)->attr = (unsigned short *)chrptr;
}
sp = sp->nextline;
}
memset(sp->text, 0, scrapwidth);
memcpy(sp->text, cp->chrbuff+rowoff, cp->scrhsize);
memset(sp->attr, 0, scrapwidth*2);
memcpy(sp->attr, cp->atrbuff+rowoff, cp->scrhsize*2);
scrapsize++;
}
/* if we saved anything, paste from our scrap */
if (scrapinit) {
pasteok = usemyscrap = 1;
}
/* return if we didn't do anything or appended new lines */
if ((!scrapinit) || scrapappend) return;
/* free lines previously appended we no longer need */
if (scrapsize < scrapalloc) {
sp = scrapstart;
sp += scrapalloc - 1; /* sp -> last permanent element */
}
nextsp = sp->nextline; /* nextsp -> first unneeded element, if any */
sp->nextline = 0; /* end chain at last element needed */
while (nextsp != 0) {
sp = nextsp;
nextsp = sp->nextline;
DisposPtr((Ptr)sp);
}
}
void dselchar(unsigned short start, unsigned short attroff, cnr *cp)
{ /* delete selected characters */
register unsigned short src, padcount;
unsigned short i, end, dest;
if (cp->fmtscrn) {
i = cp->atrbuff[attroff];
}
else i = 0;
/* calculate last position to possibly change */
if (cp->cs.repnull && cp->fmtscrn) {
if (start > 0) end = start - 1;
else end = cp->maxoff;
}
else {
end = ((start / cp->scrhsize) + 1) * cp->scrhsize - 1; /* last loc. on line */
}
src = dest = start;
padcount = 0;
while (1) {
if ((cp->atrbuff)[src] & 0x8000) {
break;
}
if ((cp->atrbuff)[src] & 0x0020) {
padcount++;
}
else {
newchar(dest, (cp->chrbuff)[src], (cp->atrbuff)[src], i, cp);
dest++;
if (dest == cp->maxcnt) dest = 0;
}
if (src == end) break; /* exit if just did the last one */
src++;
if (src == cp->maxcnt) src = 0;
}
while (padcount > 0) {
newchar(dest, 0x00, 0, i, cp);
dest++;
if (dest == cp->maxcnt) dest = 0;
padcount--;
}
newwrite(cp);
if (cp->fmtscrn) (cp->atrbuff)[attroff] |= 0x0100; /* set MDT bit */
}
void selclear(unsigned char fillchar, cnr *cp)
{
register unsigned char prot;
register short a, attroff, i;
char changeflag;
if (cp->kblock) {
beep(cp);
return;
}
changeflag = 0;
if (cp->fmtscrn) a = firstattr(cp);
else a = 0;
for (i=0; i < cp->maxcnt; i++) {
if ((cp->atrbuff)[a] & 0x8000) { /* attribute */
prot = ((cp->atrbuff)[a] & 0x2000) != 0;
attroff = a; /* save attribute offset */
}
else if (cp->fmtscrn) { /* character, formatted screen */
if (((cp->atrbuff)[a] & 0x0020) && (!prot)) {
newchar(a, fillchar, 0, (cp->atrbuff)[attroff], cp);
(cp->atrbuff)[attroff] |= 0x0100; /* set MDT bit */
changeflag = 1;
}
}
else { /* character, unformatted screen */
if ((cp->atrbuff)[a] & 0x0020) {
newchar(a, fillchar, 0, 0, cp);
changeflag = 1;
}
}
a++;
if (a == cp->maxcnt) a = 0;
}
if (changeflag) {
newwrite(cp);
}
else {
beep(cp);
kerr(1, cp);
}
}